﻿using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using IInject.Registration;

namespace IInject.Expressions
{
	/// <summary>
	/// 
	/// </summary>
	public class InjectionExpressionVisitor : ExpressionVisitor
	{
		private readonly List<InjectPropertyContext> _properties;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="properties"></param>
		public InjectionExpressionVisitor(List<InjectPropertyContext> properties)
		{
			_properties = properties;
		}

		/// <summary>
		/// Visits the children of the <see cref="T:System.Linq.Expressions.MemberExpression"/>.
		/// </summary>
		/// <returns>
		/// The modified expression, if it or any subexpression was modified; otherwise, returns the original expression.
		/// </returns>
		/// <param name="node">The expression to visit.</param>
		protected override Expression VisitMember(MemberExpression node)
		{
			var propertyContext = new InjectPropertyContext
			{
				Property = (PropertyInfo)node.Member
			};

			if (propertyContext.Property.CanWrite && !_properties.Contains(propertyContext))
			{
				_properties.Add(propertyContext);
			}

			return node;
		}

		/// <summary>
		/// Visits the children of the <see cref="T:System.Linq.Expressions.UnaryExpression"/>.
		/// </summary>
		/// <returns>
		/// The modified expression, if it or any subexpression was modified; otherwise, returns the original expression.
		/// </returns>
		/// <param name="node">The expression to visit.</param>
		protected override Expression VisitUnary(UnaryExpression node)
		{
			var expression = Visit(node.Operand);
			return node.Operand == expression ? node : expression;
		}
	}
}
